package cn.angis.system.config.satoken;

import cn.angis.common.api.ApiErrorCode;
import cn.angis.common.model.R;
import cn.angis.system.model.Resource;
import cn.angis.system.service.ResourceService;
import cn.dev33.satoken.exception.*;
import cn.dev33.satoken.stp.StpUtil;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.exception.StatusException;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Filter;
import org.noear.solon.core.handle.FilterChain;
import org.noear.solon.core.handle.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 包名称：cn.angis.system.config.satoken
 * 类名称：GlobalExceptionFilter
 * 类描述：全局异常处理
 * 创建人：@author angis.cn
 * 创建日期： 2025/3/13 19:32
 */
@Component
public class GlobalExceptionFilter implements Filter {
    protected final Logger log = LoggerFactory.getLogger(this.getClass());

    @Inject
	private ResourceService resourceService;

    /**
     * 捕获全局异常，统计执行耗时
     * @param ctx
     * @param chain
     * @throws Throwable
     */
    private void handleFilter(Context ctx, FilterChain chain) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            chain.doFilter(ctx);
        } catch (StatusException e) {
            // 自带状态码的异常，包含鉴权异常、数据校验异常、自定义业务异常
            ctx.render(R.error(e.getMessage()));
        } catch (Throwable e) {
            // 其它异常
            e.printStackTrace();
            ctx.render(R.error(e.getMessage()));
        }
        long times = System.currentTimeMillis() - start;
        log.info("请求【{}】【{}】完成，耗时:【{}ms】", ctx.path(), ctx.method(), times);
    }

    @Override
    public void doFilter(Context ctx, FilterChain chain) throws Throwable {
        if (StpUtil.isLogin()) {
            try {
                List<Resource> resourcesList = resourceService.getRouterListByUserId();
                List<Resource> allResource = resourceService.getRouterList();
                boolean auth = true;
                if (ctx.path().indexOf("update")>-1 || ctx.path().indexOf("delete")>-1) {
                    int len = resourcesList.size();
                    for (int i=0; i<len; i++) {
                        Resource resource = resourcesList.get(i);
                        if (ctx.path().equals(resource.getRoutePath()) && ctx.method().equalsIgnoreCase(resource.getHttpMethod())) {
                            StpUtil.checkPermission(resource.getPermission());
                            auth = false;
                            break;
                        }
                    }
                    len = allResource.size();
                    if (auth) {
                        for (int i=0; i<len; i++) {
                            Resource resource = allResource.get(i);
                            if (ctx.path().equals(resource.getRoutePath())) {
                                throw new NotPermissionException(resource.getPermission());
                            }
                        }
                    }
                }
                handleFilter(ctx, chain);
//                chain.doFilter(ctx);
            } catch (SaTokenException e) {
                // 不同异常返回不同状态码
                R result = null;
                if (e instanceof NotLoginException) {    // 如果是未登录异常
                    NotLoginException ee = (NotLoginException) e;
                    result = R.error(ee.getMessage());
                } else if (e instanceof NotRoleException) {        // 如果是角色异常
                    NotRoleException ee = (NotRoleException) e;
                    result = R.error("无此角色：" + ee.getRole());
                } else if (e instanceof NotPermissionException) {    // 如果是权限异常
                    NotPermissionException ee = (NotPermissionException) e;
                    result = R.error("无此权限：" + ee.getPermission());
                } else if (e instanceof DisableServiceException) {    // 如果是被封禁异常
                    DisableServiceException ee = (DisableServiceException) e;
                    result = R.error("账号被封禁：" + ee.getDisableTime() + "秒后解封");
                } else {    // 普通异常, 输出：500 + 异常信息
                    result = R.restResult(ApiErrorCode.ACCOUNT_ANOMALY, "帐号异常");
                }
                ctx.render(result);
            }
        } else {
            handleFilter(ctx, chain);
//            chain.doFilter(ctx);
        }

    }
}
